package com.huiminpay.merchant.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.huiminpay.common.cache.domain.BusinessException;
import com.huiminpay.common.cache.domain.CommonErrorCode;
import com.huiminpay.common.cache.domain.PageVO;
import com.huiminpay.common.cache.util.PhoneUtil;
import com.huiminpay.merchant.api.IMerchantService;
import com.huiminpay.merchant.convert.MerchantCovert;
import com.huiminpay.merchant.convert.StaffConvert;
import com.huiminpay.merchant.convert.StoreConvert;
import com.huiminpay.merchant.dto.MerchantDTO;
import com.huiminpay.merchant.dto.StaffDTO;
import com.huiminpay.merchant.dto.StoreDTO;
import com.huiminpay.merchant.entity.Merchant;
import com.huiminpay.merchant.entity.Staff;
import com.huiminpay.merchant.entity.Store;
import com.huiminpay.merchant.entity.StoreStaff;
import com.huiminpay.merchant.mapper.MerchantMapper;
import com.huiminpay.merchant.mapper.StaffMapper;
import com.huiminpay.merchant.mapper.StoreMapper;
import com.huiminpay.merchant.mapper.StoreStaffMapper;
import com.huiminpay.user.api.TenantService;
import com.huiminpay.user.api.dto.tenant.CreateTenantRequestDTO;
import com.huiminpay.user.api.dto.tenant.TenantDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author longlong
 * @since 2023-11-30
 */
@Slf4j
@Transactional
@Service
public class MerchantServiceImpl implements IMerchantService {

    @Autowired
    StoreMapper storeMapper;
    @Autowired
    StaffMapper staffMapper;
    @Autowired
    StoreStaffMapper storeStaffMapper;
    @Autowired
    MerchantMapper merchantMapper;
    @Reference
    TenantService tenantService;


    @Override
    public MerchantDTO queryMerchantById(Long merchantId) {
        Merchant merchant = merchantMapper.selectById(merchantId);
        MerchantDTO merchantDTO = MerchantCovert.INSTANCE.entity2Dto(merchant);
        return merchantDTO;
    }

    @Transactional
    @Override
    public MerchantDTO createMerchant(MerchantDTO merchantDTO) {
        if (ObjectUtils.isEmpty(merchantDTO)) {
            throw new BusinessException(CommonErrorCode.E_100108);
        }
        if (StringUtils.isEmpty(merchantDTO.getMobile())) {
            throw new BusinessException(CommonErrorCode.E_100112);
        }
        if (!PhoneUtil.isMatches(merchantDTO.getMobile())) {
            throw new BusinessException(CommonErrorCode.E_100109);
        }
        if (StringUtils.isBlank(merchantDTO.getUsername())) {
            throw new BusinessException(CommonErrorCode.E_100110);
        }
        if (StringUtils.isBlank(merchantDTO.getPassword())) {
            throw new BusinessException(CommonErrorCode.E_100111);
        }

        Merchant merchant = MerchantCovert.INSTANCE.dto2Entity(merchantDTO);
        LambdaQueryWrapper<Merchant> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(!StringUtils.isBlank(merchantDTO.getMobile()),
                Merchant::getMobile, merchant.getMobile());

        Integer count = merchantMapper.selectCount(queryWrapper);
        merchantMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new BusinessException(CommonErrorCode.E_100113);
        }

        //2.调用SaaS接口 添加 租户并绑定和门店 员工 商户之间的关系
        /**
         1、手机号
         2、账号
         3、密码
         4、租户类型：huimin-merchant
         5、默认套餐：huimin-merchant
         6、租户名称，同账号名
         */
        CreateTenantRequestDTO dto = new CreateTenantRequestDTO();
        dto.setMobile(merchantDTO.getMobile());
        //租户的账号信息
        dto.setUsername(merchantDTO.getUsername());
        dto.setPassword(merchantDTO.getPassword());
        //表示该租户类型是商户
        dto.setTenantTypeCode("huimin-merchant");
        //设置用户套餐为初始化套餐   //根据套餐设置权限
        dto.setBundleCode("huimin-merchant");
        //租户名称和账号名称保持一致
        dto.setName(merchantDTO.getUsername());
        //如果saas存在直接返回saas信息，如果不存在，则进行创建
        TenantDTO tenantAndAccount = tenantService.createTenantAndAccount(dto);
        //获取租户id
        if(ObjectUtils.isEmpty(tenantAndAccount)||tenantAndAccount.getId().toString()==null){
            throw new BusinessException(CommonErrorCode.E_200012);
        }
        Long tenantId = tenantAndAccount.getId();
        //租户id在商户表中唯一
        //根据租户id从商户表中查询，如过表记录存在则不允许添加商户
        Integer count1 = merchantMapper.selectCount(new LambdaQueryWrapper<Merchant>()
                .eq(Merchant::getTenantId, tenantId));
        if(count1>0){
            throw new BusinessException(CommonErrorCode.E_200017);
        }

        //设置租户和商户的绑定关系
        Merchant entity = MerchantCovert.INSTANCE.dto2Entity(merchantDTO);
        //设置对应的租户id
        entity.setTenantId(tenantId);
        //设置审核状态 0未申请 1已申请待审核 2审核通过  3拒绝审核
        entity.setAuditStatus("0");
        merchantMapper.insert(entity);

        //新增门店  创建根门店
        StoreDTO storeDTO = new StoreDTO();
        storeDTO.setStoreName("根门店");
        storeDTO.setMerchantId(entity.getId());  //商户id 也是租户id
        StoreDTO store = createStore(storeDTO);

        //新增员工
        StaffDTO staffDTO = new StaffDTO();
        staffDTO.setMobile(merchantDTO.getMobile()); //手机号
        staffDTO.setUsername(merchant.getUsername());  //设置账号
        //给员工设置门店
        staffDTO.setStoreId(store.getId());
        //设置商户id
        staffDTO.setMerchantId(entity.getId());

        StaffDTO staff = createStaff(staffDTO);

        //为门店设置管理员
        bindStaffToStore(store.getId(), staff.getId());


//        //设置审核状态0‐未申请,1‐已申请待审核,2‐审核通过,3‐审核拒绝
//        merchant.setAuditStatus("0");
//        //保存商户
//        merchantMapper.insert(merchant);
        return MerchantCovert.INSTANCE.entity2Dto(merchant);
    }


    @Transactional
    @Override
    public void applyMerchant(Long merchantId, MerchantDTO dto) {
        if (merchantId == null || ObjectUtils.isEmpty(dto)) {
            throw new BusinessException(CommonErrorCode.E_100108);
        }
        //检验mecchantId的合法性
        Merchant merchant = merchantMapper.selectById(merchantId);
        if (ObjectUtils.isEmpty(merchant)) {
            throw new BusinessException(CommonErrorCode.E_100104);
        }
        Merchant entity = MerchantCovert.INSTANCE.dto2Entity(dto);
        entity.setId(merchantId);
        entity.setMobile(merchant.getMobile());
        entity.setAuditStatus("1");
        entity.setTenantId(merchant.getTenantId());
        merchantMapper.updateById(entity);
    }

    @Override
    public MerchantDTO queryMerchantByTenantId(Long tenantId) {
        LambdaQueryWrapper<Merchant> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Merchant::getTenantId, tenantId);
        Merchant merchant = merchantMapper.selectOne(queryWrapper);
        return MerchantCovert.INSTANCE.entity2Dto(merchant);
    }


    /**
     * 商户下 新增门店
     *
     * @param storeDTO
     * @return com.huiminpay.merchant.api.dto.StoreDTO
     * @author glls
     */
    @Override
    public StoreDTO createStore(StoreDTO storeDTO) throws BusinessException {
        Store store = StoreConvert.INSTANCE.dto2entity(storeDTO);
        log.info("商户下新增门店" + JSON.toJSONString(store));
        storeMapper.insert(store);
        return StoreConvert.INSTANCE.entity2dto(store);
    }

    /**
     * 商户下 新增员工
     *
     * @param:
     * @return:
     */
    @Override
    public StaffDTO createStaff(StaffDTO staffDTO) throws BusinessException {
        //1.检验手机格式是否存在
        String mobile = staffDTO.getMobile();
        if (StringUtils.isBlank(mobile)) {
            throw new BusinessException(CommonErrorCode.E_100112);
        }
        //根据商户id和手机号校验唯一性
        if (isExistStaffByMobile(mobile, staffDTO.getMerchantId())) {
            throw new BusinessException(CommonErrorCode.E_100113);
        }
        //2.校验用户名是否为空
        String username = staffDTO.getUsername();
        if (StringUtils.isBlank(username)) {
            throw new BusinessException(CommonErrorCode.E_100110);
        }
        //根据商户id和账号校验唯一性
        if (isExistStaffByUserName(username, staffDTO.getMerchantId())) {
            throw new BusinessException(CommonErrorCode.E_100114);
        }

        Staff staff = StaffConvert.INSTANCE.dto2entity(staffDTO);
        log.info("商户下新增员工" + JSON.toJSONString(staff));
        staffMapper.insert(staff);
        return StaffConvert.INSTANCE.entity2dto(staff);
    }

    /**
     * 根据手机号判断员工是否在指定商户存在
     *
     * @param:
     * @return:
     */
    private boolean isExistStaffByMobile(String mobile, Long merchantId) {
        LambdaQueryWrapper<Staff> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(!StringUtils.isBlank(mobile), Staff::getMobile, mobile)
                .eq(Staff::getMerchantId, merchantId);
        Integer count = staffMapper.selectCount(queryWrapper);
        return count > 0;
    }

    /**
     * 根据账号判断员工是否已在指定商户存在
     *
     * @param:
     * @return:
     */
    private boolean isExistStaffByUserName(String username, Long merchantId) {
        LambdaQueryWrapper<Staff> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Staff::getUsername, username);
        queryWrapper.eq(Staff::getMerchantId, merchantId);
        Integer count = staffMapper.selectCount(queryWrapper);
        return count > 0;
    }


    /**
     * 为书店设置管理员
     *
     * @param:
     * @return:
     */
    @Override
    public void bindStaffToStore(Long storeId, Long staffId) throws BusinessException {
        StoreStaff storeStaff = new StoreStaff();
        storeStaff.setStoreId(storeId);
        storeStaff.setStaffId(staffId);
        storeStaffMapper.insert(storeStaff);
    }

    @Override
    public PageVO<StoreDTO> queryStoreByPage(StoreDTO storeDTO, Integer pageNo, Integer pageSize) {

        // 创建分页
        Page<Store> page = new Page<>(pageNo, pageSize);
        // 构造查询条件
        QueryWrapper<Store> qw = new QueryWrapper();
        if (null != storeDTO && null != storeDTO.getMerchantId()) {
            qw.lambda().eq(Store::getMerchantId, storeDTO.getMerchantId());
        }
        // 执行查询
        IPage<Store> storeIPage = storeMapper.selectPage(page, qw);
        // entity List转DTO List
        List<StoreDTO> storeList = StoreConvert.INSTANCE.listentity2dto(storeIPage.getRecords());
        // 封装结果集
        return new PageVO<>(storeList, storeIPage.getTotal(), pageNo, pageSize);
    }


    /**
     \* 查询门店是否属于某商户
     \* @param storeId
     \* @param merchantId
     \* @return
     */
    @Override
    public Boolean queryStoreInMerchant(Long storeId, Long merchantId) {
        Integer count = storeMapper.selectCount(new LambdaQueryWrapper<Store>()
                .eq(Store::getId,storeId).eq(Store::getMerchantId, merchantId));
        return count>0;
    }
}
